home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1993 / Internet Info CD-ROM (Walnut Creek) (1993).iso / networking / ip / ka9q / MacBMsrc.hqx / Mac bm Project / send.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-21  |  12.2 KB  |  578 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #ifdef MAC
  4. #include <strings.h>
  5. #include <types.h>
  6. #else
  7. #include <string.h>
  8. #endif
  9. #include <time.h>
  10. #include <ctype.h>
  11. #if    (defined(UNIX) || defined(MICROSOFT))
  12. #include <sys/types.h>
  13. #endif
  14. #include "bm.h"
  15.  
  16. struct addr *addrecip();
  17. char *ptime();
  18. #ifdef MAC
  19. extern char applroot[];
  20. #endif
  21.  
  22. /* send a message */
  23. dosmtpsend(mfp,toargs,nargs,subject)
  24. FILE *mfp;
  25. char *toargs[];
  26. int nargs;
  27. char *subject;
  28. {
  29.     char    smtp_subject[LINELEN], 
  30.         tstring[LINELEN];
  31.     char    *tmpnam();
  32.     FILE     *fpin;
  33.     char    *p;
  34. #ifdef MAC
  35.     char     *tf = "MLMXXXXXX";        /* temp file name */
  36. #else
  37.     char     *tf = "bmXXXXXX";        /* temp file name */
  38. #endif
  39.     int    c;
  40.     int    n;
  41.     long    sequence;
  42.     struct    addr *tolist,*tp;
  43.     register FILE    *tfile;
  44.     time_t    t;
  45. #ifdef MAC
  46.     char *pathname(),*ptr,sndpath[256];
  47. #endif
  48.  
  49.     if (nargs == 0) {
  50.         printf("No recpients\n");
  51.         return 0;
  52.     }
  53.     fpin = mfp;
  54.     if ((tolist = make_tolist(nargs,toargs)) == NULLADDR) {
  55.         printf("Send aborted\n");
  56.         return 0;
  57.     }
  58.  
  59.     sequence = get_msgid();
  60.  
  61.     time(&t);
  62.     mktemp(tf);
  63.         /* open textfile for write */
  64.     if ((tfile = fopen(tf,"w+")) == NULLFILE) {
  65.         perror(tf);
  66.         del_addrlist(tolist);
  67.         return 1;
  68.     }
  69.  
  70.     if (!qflag) {
  71.         /* write RFC822-compatible headers using above information */
  72.         fprintf(tfile,"Date: %s",ptime(&t));
  73.         fprintf(tfile,"Message-Id: <%ld@%s>\n",sequence,hostname);
  74.         fprintf(tfile,"From: %s@%s",username,hostname);
  75.         if (fullname != NULLCHAR && *fullname != '\0')
  76.             fprintf(tfile," (%s)",fullname);
  77.         fprintf(tfile,"\n");
  78.         if (replyto != NULLCHAR && *replyto != '\0')
  79.             fprintf(tfile,"Reply-To: %s\n",replyto);
  80.         strcpy(tstring,"To: ");
  81.         for (tp = tolist; tp != NULLADDR; tp = tp->next) {
  82.             strcat(tstring,tp->user);
  83.             if (tp->host != NULLCHAR || *tp->host != '\0') {
  84.                 strcat(tstring,"@");
  85.                 strcat(tstring,tp->host);
  86.             }
  87.             n = strlen(tstring);
  88.             if (tp->next) {
  89.                 if (n > 50) {
  90.                     fprintf(tfile,"%s,\n\t",tstring);
  91.                     if (tty) printf("%s,\n ",tstring);
  92.                     *tstring = '\0';
  93.                 } else
  94.                     strcat(tstring,", ");
  95.             }
  96.         }
  97.         fprintf(tfile,"%s\n",tstring);
  98.         if (tty) printf("%s\n",tstring); 
  99.  
  100.         *smtp_subject = '\0';
  101.         if (subject == NULL && tty) {
  102.             /* prompt and get Subject: */
  103.             printf("Subject: ");
  104.             gets(smtp_subject);
  105.         } else {
  106.             strcpy(smtp_subject,subject);
  107.             if(tty) printf("Subject: %s\n",smtp_subject);
  108.         }
  109.         fprintf(tfile,"Subject: %s\n",smtp_subject);
  110.         fprintf(tfile,"\n");       /* add empty line as separator */
  111.     }
  112.  
  113.     if (!tty && fpin == NULLFILE)
  114.         fpin = stdin;
  115.  
  116.     if (fpin != NULLFILE ) {
  117.         while((c = getc(fpin)) != EOF)
  118.             if(putc(c,tfile) == EOF)
  119.                 break;
  120.         if (ferror(tfile)) {
  121.             perror("tmp file");
  122.             (void) fclose(tfile);
  123.             return 1;
  124.         }
  125.     } else {
  126.         /* sending a message not from a file */
  127.         /* copy text from console to the file */
  128.         printf("\nType message text.  Enter a '.' or ctrl/D in column one to end.");
  129. #ifdef MAC
  130.         printf("\nCommands: ~p - redisplay msg, ~? - help\n\n");
  131. #else
  132.         printf("\nCommands: ~p - redisplay msg, ~e - invoke editor, ~? - help\n\n");
  133. #endif
  134.         for(;;) {
  135.             /* read line from console  ie stdin */
  136.             if (gets(tstring) == NULLCHAR)
  137.                 break;
  138.             rip(tstring);
  139.             if(strcmp(tstring,".") == 0 || tstring[0] == '\004')
  140.                 break;
  141.             if (*tstring == '~' ) {
  142.                 switch(tstring[1]) {
  143.                 case 'p':
  144.                     /* Print the message so far */
  145.                     fseek(tfile,0L,0);
  146.                     while (fgets(tstring,sizeof(tstring),tfile) != NULLCHAR)
  147.                         fputs(tstring,stdout);
  148.                     break;
  149. #ifndef MAC
  150.                 case 'e':
  151.                     /* Drop into editor */
  152.                     (void) fclose(tfile);
  153.                     if (editor == NULLCHAR) {
  154.                         printf("No editor defined\n");
  155.                         break;
  156.                     }
  157.                     sprintf(tstring,"%s %s",editor,tf);
  158.                     /* call editor to enter message text */
  159.                     if (system(tstring))
  160.                         printf("unable to invoke editor\n");
  161.                     tfile = fopen(tf,"a+");
  162.                     break;
  163. #endif
  164.                 case 'q':
  165.                     (void) fclose(tfile);
  166.                     (void) unlink(tf);
  167.                     printf("Abort\n");
  168.                     return 0;
  169.                 case 'r': 
  170.                     {
  171.                         FILE  *infl;
  172.                         p = &tstring[2];
  173. #ifdef MAC
  174.                         while(*p == ' ' || *p == '\t')
  175.                             p++;
  176.                         if (*p == '\0')
  177.                             printf("No file name specified\n");
  178.                         else
  179.                             ptr = pathname(applroot,p);
  180.                             strcpy(sndpath,ptr);
  181.                             free(ptr);
  182.                             if((infl = fopen(sndpath,"r")) == NULLFILE)
  183.                                 printf("No such file\n");
  184. #else
  185.                         while(*p == ' ' || *p == '\t')
  186.                             p++;
  187.                         if (*p == '\0')
  188.                             printf("No file name specified\n");
  189.                         else
  190.                             if((infl = fopen(p,"r")) == NULLFILE)
  191.                                 printf("No such file\n");
  192. #endif
  193.                             else {
  194.                                 printf("Reading file %s\n",p);
  195.                                 while((c = getc(infl)) != EOF)
  196.                                     if(putc(c,tfile) == EOF)
  197.                                         break;
  198.                                 if (ferror(tfile)) {
  199.                                     perror("tmp file");
  200.                                     (void) fclose(tfile);
  201.                                     return 1;
  202.                                 }
  203.                                 (void) fclose(infl);
  204.                             }
  205.  
  206.                         break;
  207.                     }
  208.                 case 'm': 
  209.                     {
  210.                         int    msg;
  211.                         p = &tstring[2];
  212.                         while(*p == ' ' || *p == '\t')
  213.                             p++;
  214.                         if (*p == '\0')
  215.                             msg = current;
  216.                         else
  217.                             msg = atoi(p);
  218.                         if (mfile == NULLFILE || msg < 1 || msg > nmsgs)
  219.                             printf("no such message\n");
  220.                         else {
  221.                             printf("Inserting message %d\n",msg);
  222.                             msgtofile(msg,tfile,0);
  223.                         }
  224.                         break;
  225.                     }
  226.                 case '~':
  227.                     fprintf(tfile,"%s\n",&tstring[1]);
  228.                     break;
  229.                 case '?':
  230. #ifndef MAC
  231.                     printf("~e - Invoke Editor\n");
  232. #endif
  233.                     printf("~p - Display message buffer\n");
  234.                     printf("~q - Abort this message\n");
  235.                     printf("~r file - Read file into buffer\n");
  236.                     printf("~m msg - message into buffer\n");
  237.                     printf("~~ - Enter a ~ into message\n");
  238.                     break;
  239.                 default:
  240.                     printf("Unknown ~ escape. ~? for help\n");
  241.                 }
  242.                 printf("(continue)\n");
  243.             } else
  244.                 fprintf(tfile,"%s\n",tstring);
  245.         }
  246.         printf("EOF\n");
  247.  
  248.     }
  249.     queuejob(tfile,tolist);
  250.     recordmsg(tfile,tolist->user);     /* save copy for sender */
  251.     (void) fclose(tfile);
  252.     del_addrlist(tolist);
  253.     (void) unlink(tf);
  254.     return 0;
  255. }
  256.  
  257. /* forward a message in its orginal form */
  258. bouncemsg(mfp,toargs,nargs)
  259. FILE *mfp;
  260. char *toargs[];
  261. int nargs;
  262. {
  263.     struct    addr *list;
  264.     if (nargs == 0) {
  265.         printf("No recpients\n");
  266.     } else if ((list = make_tolist(nargs,toargs)) == NULLADDR) {
  267.         printf("Bad to list\n");
  268.     } else {
  269.         queuejob(mfp,list);
  270.         del_addrlist(list);
  271.     }
  272.     return 0;
  273. }
  274.  
  275. /* Return Date/Time in Arpanet format in passed string */
  276. /* Print out the time and date field as
  277.  *        "DAY day MONTH year hh:mm:ss ZONE"
  278.  */
  279. char *
  280. ptime(t)
  281. long *t;
  282. {
  283.     register struct tm *ltm;
  284.     struct tm *localtime();
  285.     static char tz[4];
  286.     static char str[40];
  287.     extern char *getenv();
  288.     char *p;
  289.     static char *days[7] = {
  290.     "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
  291.  
  292.     static char *months[12] = {
  293.         "Jan","Feb","Mar","Apr","May","Jun",
  294.         "Jul","Aug","Sep","Oct","Nov","Dec" };
  295.  
  296.     /* Read the system time */
  297.     ltm = localtime(t);
  298.  
  299.     if (*tz == '\0')
  300.         if ((p = getenv("TZ")) == NULL)
  301.             strcpy(tz,"GMT");
  302.         else
  303.             strncpy(tz,p,3);
  304.  
  305.     /* rfc 822 format */
  306.     sprintf(str,"%s, %.2d %s %02d %02d:%02d:%02d %.3s\n",
  307.         days[ltm->tm_wday],
  308.         ltm->tm_mday,
  309.         months[ltm->tm_mon],
  310.         ltm->tm_year,
  311.         ltm->tm_hour,
  312.         ltm->tm_min,
  313.         ltm->tm_sec,
  314.         tz);
  315.     return(str);
  316. }
  317.  
  318. /* save copy in the record file */
  319. recordmsg(dfile,to) 
  320. FILE *dfile;
  321. char *to;
  322. {
  323.     register int c;
  324.     FILE     *fp;
  325.     time_t    t;
  326.  
  327.     if (record == NULLCHAR)
  328.         return 1;
  329.     fseek(dfile,0L,0);
  330.     if ((fp = fopen(record,"a")) == NULLFILE) {
  331.         printf("Unable to append to %s\n",record);
  332.     } else {
  333.         (void) time(&t);
  334.         fprintf(fp,"From %s %s",to,ctime(&t));
  335.         while((c = getc(dfile)) != EOF)
  336.             if(putc(c,fp) == EOF)
  337.                 break;
  338.         if (ferror(fp)) {
  339.             (void) fclose(fp);
  340.             return 1;
  341.         }
  342.         (void) fclose(fp);
  343.     }
  344.     return 0;
  345. }
  346.  
  347. /* place a mail job in the outbound queue */
  348. int
  349. queuejob(dfile,tolist)
  350. FILE *dfile;
  351. struct addr *tolist;
  352. {
  353.     FILE *fp;
  354. #ifdef MAC
  355.     char tmpstring[256];
  356. #else
  357.     char tmpstring[50];
  358. #endif
  359.     register struct addr *tp,*sp;
  360.     char prefix[9];
  361.     int c;
  362.     long id;
  363.  
  364.     for (tp = tolist; tp != NULLADDR; tp = tp->next) {
  365.         if (tp->sent)
  366.             continue;
  367.         fseek(dfile,0L,0);
  368.         id = get_msgid();
  369.         sprintf(prefix,"%ld",id);
  370.         (void) mlock(mqueue,prefix);
  371. #ifdef MAC
  372.         sprintf(tmpstring,"%s%s.txt",mqueue,prefix);
  373. #else
  374.         sprintf(tmpstring,"%s/%s.txt",mqueue,prefix);
  375. #endif
  376.         if((fp = fopen(tmpstring,"w")) == NULLFILE) {
  377.             printf("unable to open %s\n",tmpstring);
  378.             (void) rmlock(mqueue,prefix);
  379.             return 1;
  380.         }
  381.         while((c = getc(dfile)) != EOF)
  382.             if(putc(c,fp) == EOF)
  383.                 break;
  384.         if (ferror(fp)) {
  385.             (void) fclose(fp);
  386.             (void) rmlock(mqueue,prefix);
  387.             return 1;
  388.         }
  389.         (void) fclose(fp);
  390. #ifdef MAC
  391.         sprintf(tmpstring,"%s%s.wrk",mqueue,prefix);
  392. #else
  393.         sprintf(tmpstring,"%s/%s.wrk",mqueue,prefix);
  394. #endif
  395.         if((fp = fopen(tmpstring,"w")) == NULLFILE) {
  396.             (void) rmlock(mqueue,prefix);
  397.             return 1;
  398.         }
  399.         fprintf(fp,"%s\n%s@%s\n",tp->host,username,hostname);
  400.         fprintf(fp,"%s@%s\n",tp->user,tp->host);
  401.         tp->sent++;
  402.         /* find and other addresses to the same host */
  403.         for (sp = tp->next; sp != NULLADDR; sp = sp->next) {
  404.             if (sp->sent)
  405.                 continue;
  406.             if (strcmp(tp->host,sp->host) == 0) {
  407.                 fprintf(fp,"%s@%s\n",sp->user,sp->host);
  408.                 sp->sent++;
  409.             }
  410.         }
  411.         (void) fclose(fp);
  412.         (void) rmlock(mqueue,prefix);
  413.     }
  414.     return 0;
  415. }
  416.  
  417. #define SKIPWORD(X) while(*X && *X!=' ' && *X!='\t' && *X!='\n' && *X!= ',') X++;
  418. #define SKIPSPACE(X) while(*X ==' ' || *X =='\t' || *X =='\n' || *X == ',') X++;
  419.  
  420. /* check for and alias and expand alais into a address list */
  421. struct addr *
  422. expandalias(head, user)
  423. struct addr **head;
  424. char *user;
  425. {
  426.     FILE *fp;
  427.     register char *s,*p,*h;
  428.     int inalias;
  429.     struct addr *tp;
  430.     char buf[LINELEN];
  431.     
  432.     fp = fopen(alias, "r");
  433.     
  434.         /* no alias file found */
  435.     if (fp == NULLFILE)
  436.         return addrecip(head, user, hostname);
  437.  
  438.     inalias = 0;
  439.     while (fgets(buf,LINELEN,fp) != NULLCHAR) {
  440.         p = buf;
  441.         if ( *p == '#' || *p == '\0')
  442.             continue;
  443.         rip(p);
  444.  
  445.         /* if not in an matching entry skip continuation lines */
  446.         if (!inalias && isspace(*p))
  447.             continue;
  448.  
  449.         /* when processing an active alias check for a continuation */
  450.         if (inalias) {
  451.             if (!isspace(*p)) 
  452.                 break;    /* done */
  453.         } else {
  454.             s = p;
  455.             SKIPWORD(p);
  456.             *p++ = '\0';    /* end the alias name */
  457.             if (strcmp(s,user) != 0)
  458.                 continue;    /* no match go on */
  459.             inalias = 1;
  460.         }
  461.  
  462.         /* process the recipients on the alias line */
  463.         SKIPSPACE(p);
  464.         while(*p != '\0' && *p != '#') {
  465.             s = p;
  466.             SKIPWORD(p);
  467.             if (*p != '\0')
  468.                 *p++ = '\0';
  469.             /* find hostname */
  470.             if ((h = strchr(s,'@')) != NULLCHAR)
  471.                 *h++ = '\0';
  472.             else
  473.                 h = hostname;
  474.             tp = addrecip(head,s,h);
  475.             SKIPSPACE(p);
  476.         }
  477.     }
  478.     (void) fclose(fp);
  479.  
  480.     if (inalias)    /* found and processed and alias. */
  481.         return tp;
  482.  
  483.     /* no alias found treat as a local address */
  484.     return addrecip(head, user, hostname);
  485. }
  486.  
  487. /* convert a arg list to an list of address structures */
  488. struct addr *
  489. make_tolist(argc,argv)
  490. int argc;
  491. char *argv[];
  492. {
  493.     struct addr *tolist, *tp;
  494.     char *user, *host;
  495.     int i;
  496.     tolist = NULLADDR;
  497.     for (i = 0; i < argc; i++) {
  498.         user = argv[i];
  499.         if ((host = strchr(user ,'@')) != NULLCHAR) {
  500.             *host++ = '\0';
  501.             /* if it matches our host name */
  502.             if (stricmp(host,hostname) == 0)
  503.                 host = NULLCHAR;
  504.         }
  505.  
  506.         if (host == NULLCHAR)    /* a local address */
  507.             tp = expandalias(&tolist,user);
  508.         else        /* a remote address */
  509.             tp = addrecip(&tolist, user, host);
  510.  
  511.         if (tp == NULLADDR) {
  512.             printf("Out of memory\n");
  513.             del_addrlist(tolist);
  514.             return NULLADDR;
  515.         }
  516.     }
  517.     return tolist;
  518. }
  519.  
  520. /* delete a list of mail addresses */
  521. del_addrlist(list)
  522. struct addr *list;
  523. {
  524.     struct addr *tp, *tp1;;
  525.     for (tp = list; tp != NULLADDR; tp = tp1) {
  526.         tp1 = tp->next;
  527.         if (tp->user != NULLCHAR);
  528.             free(tp->user);
  529.         if (tp->host != NULLCHAR);
  530.             free(tp->host);
  531.         (void) free((char *)tp);
  532.     }
  533. }
  534.  
  535. /* add an address to the from of the list pointed to by head 
  536. ** return NULLADDR if out of memory.
  537. */
  538. struct addr *
  539. addrecip(head,user,host)
  540. struct addr **head;
  541. char *user, *host;
  542. {
  543.     register struct addr *tp;
  544.  
  545.     tp = (struct addr *)calloc(1,sizeof(struct addr));
  546.     if (tp == NULLADDR)
  547.         return NULLADDR;
  548.  
  549.     tp->next = NULLADDR;
  550.  
  551.     /* allocate storage for the user's login */
  552.     if ((tp->user = malloc((unsigned)strlen(user)+1)) == NULLCHAR) {
  553.         (void) free((char *)tp);
  554.         return NULLADDR;
  555.     }
  556.     strcpy(tp->user,user);
  557.  
  558.     /* allocate storage for the host name */
  559.     if (host != NULLCHAR)
  560.         if ((tp->host = malloc((unsigned)strlen(host)+1)) == NULLCHAR) {
  561.             (void) free(tp->user);
  562.             (void) free((char *)tp);
  563.             return NULLADDR;
  564.         }
  565.     strcpy(tp->host,host);
  566.  
  567.     /* add entry to front of existing list */
  568.     if (*head == NULLADDR)
  569.         *head = tp;
  570.     else {
  571.         tp->next = *head;
  572.         *head = tp;
  573.     }
  574.     return tp;
  575.  
  576. }
  577.  
  578.